home *** CD-ROM | disk | FTP | other *** search
- /* ==========================================================================
-
- File: WorkDiamondWinds.c
- Function: Controls Diamond Windows.
- History: 7/4/90 & 8/26/90 - 1/16/91 & 2/15/91 & 4/15/91 - 4/22/91 : Marz.
-
- This file contains additional code illustrating the appropriate methodology for
- operating Diamond Windows.
-
- ============================================================================= */
-
- #include "WindowMgr.h"
- #include "DiamondDef.h"
-
-
- #define NO_VARIATION 0
- #define wJUST_DRAGGED 50
- #define wNEW_TITLE 51
-
- #define FLUSH_EVENTS 0
- #define VISIBLE TRUE
- #define DIAMOND_DOC_PROC_PLUS_ZOOM 16008
- #define NO_GROW_DIAMOND_PROC 16012
- #define PLACE_IN_FRONT -1L
- #define GO_AWAY_BOX TRUE
- #define NULL_REF_NUM 0
-
-
- typedef struct ZoomInfo {
- short top;
- short midX;
- short length;
- } ZoomInfo;
-
-
- EventRecord theEvent;
-
- /* ========================================================================= */
-
-
- void ZoomDiamondFrame(theWindow, expand)
- WindowPeek theWindow;
- Boolean expand;
- {
- /* This function expands or shrinks a series of diamonds around the About
- Diamond when it is being Zoomed. It's a very nice effect because it takes the
- user's mind off how long it's taking her or his window's contents to be redrawn
- and it also it looks cool.
- ****************************** Acknowledgement***********************************
- I found a routine for drawing zoom indicator lines around windows in the
- Febuary 1987 issue of MacTutor. I modified the original code written by Jean
- Decombe so that it would work well with diamond shaped windows and optimized it
- a touch by performing all division operations as bit shifts, using the Line()
- command instead of LineTo(), and by using the % {mod} function to reduce the
- number of necessary storage areas {normally rectangles, ZoomInfos in this case}.
- */
- GrafPtr savedPort, deskPort;
- Rect startRect, endRect, zoomRect;
- long unit;
- short index, topDiff, leftDiff, bottomDiff, rightDiff;
- ZoomInfo zoomSpot[4], holder;
-
- startRect = ((WStateData*) *(theWindow->dataHandle))->stdState;
- endRect = ((WStateData*) *(theWindow->dataHandle))->userState;
- InsetRect(&startRect, -26, -26);
- InsetRect(&endRect, -26, -26);
- if (expand)
- {
- zoomRect = startRect;
- startRect = endRect;
- endRect = zoomRect;
- }
- topDiff = endRect.top - startRect.top;
- leftDiff = endRect.left - startRect.left;
- bottomDiff = endRect.bottom - startRect.bottom;
- rightDiff = endRect.right - startRect.right;
- GetPort(&savedPort);
- GetWMgrPort(&deskPort);
- InitPort(deskPort);
- PenMode(notPatXor);
- PenPat(&white);
- for (index = 0; index <= 20; index ++)
- {
- if (index >= 4)
- {
- holder = zoomSpot[index % 4];
- MoveTo(holder.midX, holder.top);
- Line(holder.length, holder.length);
- Line(-holder.length, holder.length);
- Line(-holder.length, -holder.length);
- Line(holder.length, -holder.length);
- }
- if (index <= 16)
- {
- zoomRect = startRect;
- unit = ((expand ? index + 1: 33 - index) * index) >> 1;
- zoomRect.top += (unit * topDiff) >> 7;
- zoomRect.left += (unit * leftDiff) >> 7;
- /* zoomRect.bottom never needs to be adjusted because diamond shaped windows
- grow in the horizontal and vertical directions at the same rate.
- */
- zoomRect.right += (unit * rightDiff) >> 7;
- holder.top = zoomRect.top;
- holder.midX = (zoomRect.right + zoomRect.left) >> 1;
- holder.length = (zoomRect.right - zoomRect.left) >> 1;
- MoveTo(holder.midX, holder.top);
- Line(holder.length, holder.length);
- Line(-holder.length, holder.length);
- Line(-holder.length, -holder.length);
- Line(holder.length, -holder.length);
- zoomSpot[index % 4] = holder;
- }
- }
- PenMode(patCopy);
- PenPat(&black);
- SetPort(savedPort);
- }
-
-
-
- Boolean DoMouseDown(thePart, theWindow)
- short thePart;
- WindowPtr theWindow;
- {
- /* Handles mouse clicks. Returns TRUE if the window was clicked in its close
- box.
- */
- Boolean disposedWindow = FALSE;
- Handle wDefHdl;
- long newSize;
- Rect growRect, sizeRestrict, theRect;
- RgnHandle theRgn, strucRectRgn;
- short adjust, offset, currentSize;
- WindowPeek windPkr;
-
- if (theWindow != NULL)
- SetPort(theWindow);
- switch(thePart)
- {
- case inDesk:
- case inSysWindow:
- SystemClick(&theEvent, theWindow);
- break;
- case inDrag:
- windPkr = (WindowPeek) theWindow;
- /* The Window Manger automatically calls WDEFs passing the wDraw message when
- part of a window is dragged back onscreen after having been offscreen. This
- segment of code sets the dragged member of the DataRecord structure, if the WDEF
- is called the dragged member will be set to FALSE. If it remains TRUE after the
- DragWindow() procedure has been executed then the window's regions need to be
- updated and the WDEF is called to achieve this.
- All this is necessary because when a window is dragged offscreen and then
- back on, the WDEF must recalculate its regions BEFORE redrawing the window, so
- that the full visible portion of the window is redrawn.
- */
- windPkr->titleWidth = TRUE;
- DragWindow(theWindow, theEvent.where, &screenBits.bounds);
- /* The WDEF should only be called here when <dataRecord>dragged == FALSE.
- Otherwise the diamond window's regions would be recalculated twice {what a
- waste}. The Diamond WDEF automatically sets <dataRecord>.dragged to FALSE when
- called with the wJUST_DRAGGED message.
- */
- if (windPkr->titleWidth)
- {
- wDefHdl = windPkr->windowDefProc;
- HLock(wDefHdl);
- CallPascalL(NO_VARIATION, windPkr, wJUST_DRAGGED, 0L, *wDefHdl);
- HUnlock(wDefHdl);
- }
- if (theWindow != FrontWindow())
- if (!(theEvent.modifiers & cmdKey))
- SelectWindow(theWindow);
- break;
- case inGrow:
- /* The size restriction is actually 50 for the lower limit and 400 for
- the upper limit. However, due to the nature of Diamond Windows only
- half these values are used.
- */
- growRect = theWindow->portRect;
- currentSize = (growRect.right - growRect.left) >> 1;
- sizeRestrict.top = sizeRestrict.left = currentSize + 28;
- sizeRestrict.bottom = sizeRestrict.right = currentSize + 200;
- newSize = GrowWindow(theWindow, theEvent.where, &sizeRestrict);
- /* adjust originally holds a value which is too large, again due to the rate at
- which diamond windows grow and shrink. This value is ANDed with 0xFFFE to ensure
- that the resultant number is even. The result must then be manipulated so that
- it corresponds to the actual new size the window should be.
- */
- /* Only HiWord() because movement left or right is inconsequential. */
- adjust = HiWord(newSize) & MAKE_EVEN;
- if ((adjust != 0) && (adjust != (currentSize << 1)))
- {
- /* in case the origin has been offset */
- offset = (adjust - (growRect.right - growRect.left));
- LocalToGlobal(&topLeft(growRect));
- ShowHide(theWindow, FALSE);
- SizeWindow(theWindow, adjust + offset, adjust + offset, FALSE);
- MoveWindow(theWindow, growRect.left - offset,
- growRect.top - offset, TRUE);
- ShowHide(theWindow, TRUE);
- }
- break;
- case inGoAway:
- if (TrackGoAway(theWindow, theEvent.where))
- {
- DisposeWindow(theWindow);
- disposedWindow = TRUE;
- }
- break;
- case inContent:
- if (theWindow != FrontWindow())
- SelectWindow(theWindow);
- break;
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(theWindow, theEvent.where, thePart))
- {
- ZoomDiamondFrame((WindowPeek) theWindow, thePart == inZoomOut);
- ShowHide(theWindow, FALSE);
- ZoomWindow(theWindow, thePart, TRUE);
- ShowHide(theWindow, TRUE);
- }
- break;
- }
- return(disposedWindow);
- }
-
-
-
- void UpdateDiamond(theWindow)
- WindowPeek theWindow;
- {
- Rect rgnRect = {20, 10, 180, 190};
-
- PaintRect(&rgnRect);
- }
-
-
-
- void SetDiamondWTitle(theWindow, newTitle)
- Ptr theWindow;
- Str255 newTitle;
- {
- /* Use the following lines to change a diamond window's title.
- */
- Handle wDefHdl;
-
- wDefHdl = ((WindowPeek) theWindow)->windowDefProc;
- HLock(wDefHdl);
- CallPascalL(0, theWindow, wNEW_TITLE, newTitle, *wDefHdl);
- HUnlock(wDefHdl);
- }
-
-
-
- void DiamondWindowTest()
- {
- /* Operates diamond shaped windows demonstrating many of the WDEF's abilities.
- */
- GrafPtr oldPort;
- Handle wDefHdl;
- Rect windRect = {50, 50, 215, 215}, theRect;
- short openWindows, thePart;
- Str255 newTitle = "\pThe Only Window";
- WindowPtr theWindow;
-
- NewWindow(NULL, &windRect, "\pDiamond Window", VISIBLE,
- DIAMOND_DOC_PROC_PLUS_ZOOM, PLACE_IN_FRONT, GO_AWAY_BOX, NULL_REF_NUM);
- /* When you wish to define diamond windows from resource definitions, everything
- should be set up normally. Then, once you are satisfied with the configuration,
- go back and add an offset to the procID member to reflect the use of a custom
- WDEF. The offset is the ID number assigned to the WDEF multiplied by 16. In
- this case the ID number was 1000, so the offset is (16 * 1000) or 16000. However,
- DIAMOND_DOC_PROC_PLUS_ZOOM = 16008. The additional 8 specifies that the window
- should have one of each of the following regions: grow, goAway, and zoom.
- */
- InsetRect(&windRect, -20, -40); /* these will be equalized by the WDEF */
- OffsetRect(&windRect, 130, 55);
- NewWindow(NULL, &windRect, "\pAnother Diamond Window", VISIBLE,
- NO_GROW_DIAMOND_PROC, PLACE_IN_FRONT, GO_AWAY_BOX, NULL_REF_NUM);
- openWindows = 2;
- do
- {
- WaitNextEvent(everyEvent, &theEvent, 0L, 0L);
- theWindow = (WindowPtr) theEvent.message;
- if (theWindow != NULL)
- SetPort(theWindow);
- switch(theEvent.what)
- {
- case mouseDown:
- thePart = FindWindow(theEvent.where, &theWindow);
- if (DoMouseDown(thePart, theWindow))
- {
- openWindows --;
- if (openWindows == 1)
- {
- theWindow = FrontWindow();
- SetDiamondWTitle(theWindow, newTitle);
- /* Demostration of SetOrigin() */
- SetPort(theWindow);
- SetOrigin(-30, -50);
- windRect = theWindow->portRect;
- /* Must also offset the clipRgn so that it corresponds with the new window
- coordinates.
- */
- if ( (**((DataRecordHdl) ((WindowPeek) theWindow)->
- dataHandle)).resizable)
- OffsetRgn(theWindow->clipRgn, -30, -50);
- else
- InsetRect(&windRect, -26, -26);
- EraseRect(&windRect);
- InvalRect(&windRect);
- }
- }
- break;
- case activateEvt:
- case updateEvt:
- GetPort(&oldPort);
- SetPort(theWindow);
- DrawGrowIcon(theWindow);
- BeginUpdate(theWindow);
- UpdateDiamond((WindowPeek) theWindow);
- EndUpdate(theWindow);
- SetPort(oldPort);
- break;
- }
- }
- while (openWindows > 0);
- }
-
-
-
- void main()
- {
- /* Initializes the ToolBox and calls the window handling function.
- */
- Ptr reservedMem;
- Rect screenRect;
- short index;
-
- MaxApplZone();
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- TEInit();
- InitDialogs(NULL);
- InitMenus();
- FlushEvents(everyEvent, FLUSH_EVENTS);
- InitCursor();
- DiamondWindowTest();
- ExitToShell();
- }
-
-
-
-